﻿using HslCommunication.ModBus;

using Newtonsoft.Json;

using Prism.Commands;
using Prism.Mvvm;

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;

namespace TestHsl.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public MainWindowViewModel()
        {
            AppDomain.CurrentDomain.ProcessExit += OnExit;
            if (!HslCommunication.Authorization.SetAuthorizationCode("7f191e5b-4f49-40e3-9049-c69ba254e2c3"))
            {
                System.Windows.MessageBox.Show("通讯授权失败");
                return;   // 激活失败应该退出系统
            }

            bkgWorker = new BackgroundWorker { WorkerSupportsCancellation = true };
            bkgWorker.DoWork += Background;

            LoadConfig();
        }
        private void OnExit(object sender, EventArgs e)
        {

            modbusTcp?.Dispose();
            bkgWorker.CancelAsync();
            bkgWorker.Dispose();
        }
        private void Background(object sender, DoWorkEventArgs e)
        {
            var worker = (BackgroundWorker)sender;
            while (!worker.CancellationPending)
            {
                if (MWS is null or { Count: < 1 }) goto sleep;
                lock (this) { 
                for (int i = 0; i < MWS.Count; i++)
                {

                    var content = modbusTcp.ReadInt16(MWS[i].Address);

                    MWS[i].IsSuccess = content.IsSuccess;
                    if (content.IsSuccess)
                    {
                        MWS[i].Value = content.Content;
                    }

                }
                }
            sleep:

                Thread.Sleep(SleepTime);
            }
        }
        private string _IP = "127.0.0.1";
        public string IP
        {
            get { return _IP; }
            set { SetProperty(ref _IP, value); }
        }

        private DelegateCommand _Open;
        public DelegateCommand Open =>
            _Open ??= new DelegateCommand(ExecuteOpen);

        private ModbusTcpNet modbusTcp;
        void ExecuteOpen()
        {
            if (!IPAddress.TryParse(IP, out IPAddress ip))
            {

                System.Windows.MessageBox.Show("IP错误");
                return;
            }
            IP = ip.ToString();
            modbusTcp = new(IP, 502);


            // 重置最大值，这样的话，消息号就在0-1000
            modbusTcp.MessageId.ResetMaxValue(10000);

            // 如果我们需要一直保持消息号在0，不需要增长的计数
            modbusTcp.MessageId.IncreaseTick = 0;

            modbusTcp.ConnectServer();

            modbusTcp.ConnectTimeOut = 30;
            if (!bkgWorker.IsBusy)
                bkgWorker.RunWorkerAsync();

            SaveConfig();

        }

        private bool _IsOpen;
        public bool IsOpen
        {
            get { return _IsOpen; }
            set { SetProperty(ref _IsOpen, value); }
        }

        private ObservableCollection<MW> _MWS = new();
        public ObservableCollection<MW> MWS
        {
            get { return _MWS; }
            set { SetProperty(ref _MWS, value); }
        }
        private int _From;
        public int From
        {
            get { return _From; }
            set { SetProperty(ref _From, value); }
        }

        private int _Count = 1;
        public int Count
        {
            get { return _Count; }
            set { SetProperty(ref _Count, value); }
        }


        private DelegateCommand _Add;
        public DelegateCommand Add =>
            _Add ??= new DelegateCommand(ExecuteAdd);

        void ExecuteAdd()
        {
            for (int i = From; i < From + Count; i++)
            {
                if (!MWS.Any(m => m.Address == i.ToString()))
                    MWS.Add(new MW() { Address = i.ToString() });
            }
            SaveConfig();
        }

        private DelegateCommand _Remove;
        public DelegateCommand Remove =>
            _Remove ??= new DelegateCommand(ExecuteRemove);

        void ExecuteRemove()
        {
            lock(this)
            for (int i = From; i < From + Count; i++)
            {

                var m = MWS.Where(m => m.Address == i.ToString()).FirstOrDefault();
                if(m != null)
                    MWS.Remove(m);
                    
            }
            SaveConfig();
        }
        private readonly BackgroundWorker bkgWorker;
        private int _SleepTime = 10;
        public int SleepTime
        {
            get { return _SleepTime; }
            set { SetProperty(ref _SleepTime, value); }
        }
        #region Config


        private DelegateCommand _Save;
        public DelegateCommand Save =>
            _Save ??= new DelegateCommand(ExecuteSave);

        void ExecuteSave()
        {
            SaveConfig();
        }
        private void LoadConfig()
        {
            if (!Directory.Exists("./Config/"))
            {
                Directory.CreateDirectory("./Config/");
            };
            if (File.Exists("./Config/PLC.json"))
            {
                var json = File.ReadAllText("./Config/PLC.json");
                dynamic config = JsonConvert.DeserializeObject(json);
                IP = config.IP;
                From = config.From;
                Count = config.Count;
                SleepTime = config.SleepTime;
            }
            else
            {
                SaveConfig();

            }

        }


        private void SaveConfig()
        {


            dynamic config = new { IP, From, Count, SleepTime };

            var json = JsonConvert.SerializeObject(config);

            File.WriteAllText("./Config/PLC.json", json);
        }
        #endregion
    }
}
